/******************************************************************************
 * FileName:    gwin_remote_gwin.c
 * Desc:        遥控
 *                  广云协议
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

/*-------------------------- Includes ---------------------------------------*/
#include "gwin_board.h"
#include "gwin_remote.h"
#include "gwin_main_task.h"
#include "gwin_security.h"

#include "gwin_protocol_task.h"


/*-------------------------- Macro Definitions ------------------------------*/
#define LOCAL_DEBUG_EN                      ( 0 )
#if LOCAL_DEBUG_EN
#define GWIN_DEBUG(...)                     USER_DEBUG(__VA_ARGS__)
#else
#define GWIN_DEBUG(...)
#endif


#define GWIN_COMPANY_ID_H_1                 0x01        // 加密（adv type : Service UUIDs 0x07）
#define GWIN_COMPANY_ID_L_1                 0x01
#define GWIN_COMPANY_ID_H_2                 0x46        // 加密（adv type : Manufacturer Specific Data 0xFF）
#define GWIN_COMPANY_ID_L_2                 0x0C
#define GWIN_COMPANY_ID_H_3                 0x01        // 明文（adv type : Service UUIDs 0x07）
#define GWIN_COMPANY_ID_L_3                 0x02


/*-------------------------- Type Declarations ------------------------------*/
/**
 * @brief 遥控协议 偏移
 *
 *      遙控协议  Adv Data单元格式: Len + Type + Data
 *          Adv Data : 0x11 0x07 16Byte数据
 *                                  厂商id（2Byte） + 遥控id（4Byte） + 指令id（1Byte） + 分组id（1Byte） + 随机id（1Byte） + 按键id（1Byte） + 小程序预留（4Byte） + 接收端转发标志位/小程序/APP（1Byte） + 遥控器为0x00 + 和校验（1Byte）
 *                                  广云：0x01 0x01
 */
typedef enum
{
    GWIN_REMOTE_PROT_INDEX_LEN,
    GWIN_REMOTE_PROT_INDEX_TYPE,
    GWIN_REMOTE_PROT_INDEX_COMPANY_1,
    GWIN_REMOTE_PROT_INDEX_COMPANY_2,
    GWIN_REMOTE_PROT_INDEX_REMOTE_1,
    GWIN_REMOTE_PROT_INDEX_REMOTE_2,
    GWIN_REMOTE_PROT_INDEX_REMOTE_3,
    GWIN_REMOTE_PROT_INDEX_REMOTE_4,
    GWIN_REMOTE_PROT_INDEX_CMD,
    GWIN_REMOTE_PROT_INDEX_GROUP,
    GWIN_REMOTE_PROT_INDEX_RAND,
    GWIN_REMOTE_PROT_INDEX_BTN,
    GWIN_REMOTE_PROT_INDEX_WECHAT_1,
    GWIN_REMOTE_PROT_INDEX_WECHAT_2,
    GWIN_REMOTE_PROT_INDEX_WECHAT_3,
    GWIN_REMOTE_PROT_INDEX_WECHAT_4,
    GWIN_REMOTE_PROT_INDEX_WECHAT_5,
    GWIN_REMOTE_PROT_INDEX_CHECK_SUM,
    GWIN_REMOTE_PROT_INDEX_MAX,
}gwin_remote_prot_index_t;
#define GWIN_REMOTE_PROT_PAYLOAD_START      ( GWIN_REMOTE_PROT_INDEX_COMPANY_1 )    // 负载数据（和校验）开始
#define GWIN_REMOTE_PROT_PAYLOAD_END        ( GWIN_REMOTE_PROT_INDEX_WECHAT_5 )     // 负载数据（和校验）结束
#define GWIN_REMOTE_PROT_PAYLOAD_LEN        ( GWIN_REMOTE_PROT_PAYLOAD_END - GWIN_REMOTE_PROT_PAYLOAD_START + 1 )       // 负载数据长度
#define GWIN_REMOTE_PROT_ENCRYPTED_START    ( GWIN_REMOTE_PROT_INDEX_BTN )          // 加密数据开始
#define GWIN_REMOTE_PROT_ENCRYPTED_END      ( GWIN_REMOTE_PROT_INDEX_WECHAT_5 )     // 加密数据结束
#define GWIN_REMOTE_PROT_ENCRYPTED_LEN      ( GWIN_REMOTE_PROT_ENCRYPTED_END - GWIN_REMOTE_PROT_ENCRYPTED_START + 1)    // 加密数据长度
#define GWIN_REMOTE_PROT_ENCRYPTED_INDEX(i) ( i - GWIN_REMOTE_PROT_ENCRYPTED_START) // 加密数据编号


/**
 * @brief 遥控按键编号
 */
typedef enum
{
    GWIN_RB_INDEX_NONE,
    GWIN_RB_INDEX_SP_TOTAL_TURN_ON,
    GWIN_RB_INDEX_SP_TOTAL_TURN_OFF,
    GWIN_RB_INDEX_SP_GROUP_1,
    GWIN_RB_INDEX_SP_GROUP_2,
    GWIN_RB_INDEX_SP_GROUP_3,
    GWIN_RB_INDEX_SP_GROUP_4,
    GWIN_RB_INDEX_SP_GROUP_5,
    GWIN_RB_INDEX_SP_GROUP_6,
    GWIN_RB_INDEX_SP_GROUP_7,
    GWIN_RB_INDEX_SP_GROUP_8,
    GWIN_RB_INDEX_SP_GROUP_9,
    GWIN_RB_INDEX_BRIGHTNESS_ADD,
    GWIN_RB_INDEX_BRIGHTNESS_SUB,
    GWIN_RB_INDEX_TEMP_COLOUR_ADD,
    GWIN_RB_INDEX_TEMP_COLOUR_SUB,
    GWIN_RB_INDEX_FIXED_MODE_NEXT,
    GWIN_RB_INDEX_FILL_LIGHT,
    GWIN_RB_INDEX_SCENE_1,
    GWIN_RB_INDEX_SCENE_2,
    GWIN_RB_INDEX_SCENE_3,
    GWIN_RB_INDEX_SCENE_4,
    GWIN_RB_INDEX_FIXED_MODE_NEUTRAL,
    GWIN_RB_INDEX_FIXED_MODE_YELLOW,
    GWIN_RB_INDEX_FIXED_MODE_WRITE,
    GWIN_RB_INDEX_FIXED_MODE_SMALL_NIGHT_LIGHT,
    GWIN_RB_INDEX_MAX,
}gwin_remote_btn_index_t;
#define GWIN_REMOTE_BTN_SHORT_PRESS         ( 0x01 - 1 )    // 短按按下开始
#define GWIN_REMOTE_BTN_SHORT_RELEASE       ( 0x1A - 1 )    // 短按松开开始
#define GWIN_REMOTE_BTN_LONG_PRESS          ( 0x33 - 1 )    // 长按按下开始
#define GWIN_REMOTE_BTN_LONG_RELEASE        ( 0x4C - 1 )    // 长按松开开始
#define GWIN_REMOTE_BTN_NET_RESET           ( 0x66 )        // 其他 双长按 重新配网
#define GWIN_REMOTE_BTN_FACTORY_TEST        ( 0x6F )        // 其他 双长按 工厂测试
#define GWIN_REMOTE_BTN_FACTORY_RESET       ( 0x70 )        // 其他 双长按 恢复出厂
#define GWIN_REMOTE_BTN_RESET_ALL_FORCE     ( 0x72 )        // 其他 双长按 强制复位所有参数（研发预留接口，防止错误，不带做灯光功能，直接响应）
#define GWIN_REMOTE_BTN_WECHAT              ( 0xFF )        // 其他 微信小程序

/**
 * @brief 遥控按键编号 V8
 */
typedef enum
{
    GWIN_RB_V8_INDEX_NONE,
    GWIN_RB_V8_INDEX_SP_TOTAL,
    GWIN_RB_V8_INDEX_SP_GROUP_1_TURN_ON,
    GWIN_RB_V8_INDEX_SP_GROUP_2_TURN_ON,
    GWIN_RB_V8_INDEX_SP_GROUP_3_TURN_ON,
    GWIN_RB_V8_INDEX_SP_GROUP_4_TURN_ON,
    GWIN_RB_V8_INDEX_SP_GROUP_1_TURN_OFF,
    GWIN_RB_V8_INDEX_SP_GROUP_2_TURN_OFF,
    GWIN_RB_V8_INDEX_SP_GROUP_3_TURN_OFF,
    GWIN_RB_V8_INDEX_SP_GROUP_4_TURN_OFF,
    GWIN_RB_V8_INDEX_SCENE_5,
    GWIN_RB_V8_INDEX_SCENE_6,
    GWIN_RB_V8_INDEX_NET_RESET,
    GWIN_RB_V8_INDEX_RHYTHM_TURN_ON,
    GWIN_RB_V8_INDEX_RHYTHM_TURN_OFF,
    GWIN_RB_V8_INDEX_DYNAMIC_0,
    GWIN_RB_V8_INDEX_MAX,
}gwin_remote_v8_btn_index_t;
#define GWIN_REMOTE_BTN_V8_SHORT_PRESS      ( 0x7E - 1 )    // 短按按下开始
#define GWIN_REMOTE_BTN_V8_SHORT_RELEASE    ( 0x97 - 1 )    // 短按松开开始
#define GWIN_REMOTE_BTN_V8_LONG_PRESS       ( 0xB0 - 1 )    // 长按按下开始
#define GWIN_REMOTE_BTN_V8_LONG_RELEASE     ( 0xC9 - 1 )    // 长按松开开始


/**
 * @brief 遥控按键编号
 */
typedef enum
{
    GWIN_REMOTE_WECHAT_CMD_NONE,
    GWIN_REMOTE_WECHAT_CMD_TEMP_COLOUR,
    GWIN_REMOTE_WECHAT_CMD_BRIGHTNESS,
    GWIN_REMOTE_WECHAT_CMD_FIX_SCENE,
    GWIN_REMOTE_WECHAT_CMD_BRIGHTNESS_TEMP_COLOUR,
    GWIN_REMOTE_WECHAT_CMD_RHYTHM,
}gwin_retmote_wechat_cmd;


/*-------------------------- Global Variables -------------------------------*/
/**
 * @brief 系统参数
 */
extern system_param_t system_param;


/*-------------------------- Local Variables --------------------------------*/
/**
 * @brief 遙控协议头
 *          Adv Data单元格式: Len + Type + Data
 *          Adv Data1 + Adv Data2
 */
static const uint8_t remote_prot_head_1[] = { 0x11, 0x07, GWIN_COMPANY_ID_H_1, GWIN_COMPANY_ID_L_1 };
static const uint8_t remote_prot_head_2[] = { 0x11, 0xFF, GWIN_COMPANY_ID_H_2, GWIN_COMPANY_ID_L_2 };
#if GWIN_REMOTE_CLEARTEXT
static const uint8_t remote_prot_head_3[] = { 0x11, 0x07, GWIN_COMPANY_ID_H_3, GWIN_COMPANY_ID_L_3 };
#endif
static const uint8_t remote_prot_head_cnt = 4;

static uint8_t is_cleartext_prot = 0;


/*-------------------------- Functions Declarations -------------------------*/

/*-------------------------- Functions Definitions --------------------------*/
/**
 * @brief 数据校验
 *          和校验
 */
static uint8_t gwin_remote_data_check(uint8_t *data, uint8_t len)
{
    uint8_t sum = 0;

    for (uint8_t i = 0; i < len; i++)
    {
        sum += data[i];
    }

    return sum;
}


/**
 * @brief 遥控配对
 */
static uint8_t gwin_remote_pair(remote_pair_info_t *remote_pair_info, uint8_t btn_id, uint8_t *action)
{
    uint8_t ret = 0;

    if (btn_id == GWIN_REMOTE_BTN_FACTORY_TEST)
    {
        ret = 1;

        if (!system_param.factory_enter_disable)            // 厂测阶段才能开工厂测试
        {
            *action = MAIN_TASK_MSG_EX_ACT_SUBTYPE_FACTORY_TEST;
        }
    }

    return ret;
}


/**
 * @brief 遥控 判断协议
 *          广云协议
 */
int8_t gwin_remote_date_check_gwin(uint8_t *data, uint16_t len, remote_pair_info_t *remote_pair_info, uint8_t *adv_payload_pos, uint8_t *cmd_index)
{
    uint8_t find_head = 0;
    uint8_t _adv_payload_pos = 0;
    adv_payload_unit_t *adv_payload_unit = NULL;
    while (_adv_payload_pos < len)
    {
        adv_payload_unit = (adv_payload_unit_t *)&data[_adv_payload_pos];
        if (adv_payload_unit->len < ADV_PAYLOAD_UNIT_LEN_MIN            // 防止不按照蓝牙格式
                || adv_payload_unit->len > ADV_PAYLOAD_UNIT_LEN_MAX)    // 防止不按照蓝牙格式
        {
            break;
        }
        if (memcmp(remote_prot_head_1, adv_payload_unit, remote_prot_head_cnt) == 0
                || memcmp(remote_prot_head_2, adv_payload_unit, remote_prot_head_cnt) == 0)
        {
            is_cleartext_prot = 0;
            find_head = 1;
            break;
        }
        #if GWIN_REMOTE_CLEARTEXT
        else if (memcmp(remote_prot_head_3, adv_payload_unit, remote_prot_head_cnt) == 0)
        {
            is_cleartext_prot = 1;
            find_head = 1;
            break;
        }
        #endif
        _adv_payload_pos += (adv_payload_unit->len + 1);
    }
    if (!find_head)
    {
        return -1;
    }
    data = (uint8_t *)adv_payload_unit;

    // 和校验
    uint8_t check_sum = gwin_remote_data_check(&data[GWIN_REMOTE_PROT_PAYLOAD_START], GWIN_REMOTE_PROT_PAYLOAD_LEN);
    if (check_sum != data[GWIN_REMOTE_PROT_INDEX_CHECK_SUM])
    {
        return -2;
    }

    *adv_payload_pos = _adv_payload_pos;
    memcpy(remote_pair_info->remote_id, &data[GWIN_REMOTE_PROT_INDEX_REMOTE_1], sizeof(remote_pair_info->remote_id));
    remote_pair_info->group_id |= (0x01 << data[GWIN_REMOTE_PROT_INDEX_GROUP]);              // 按位处理，同一个遥控不同分组只占一个存储空间
    *cmd_index = data[GWIN_REMOTE_PROT_INDEX_CMD];

    return 0;
}

/**
 * @brief 遥控接收数据
 */
void gwin_remote_date_proc_gwin(uint8_t *data, uint16_t len, remote_pair_info_t *remote_pair_info, uint8_t *_action, uint32_t *_param)
{
    uint8_t decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_LEN] = { 0x00 };
    uint8_t cmd_id = 0;
    uint8_t rand_id = 0;
    uint8_t btn_id = 0;
    uint8_t action = 0;

    // 数据解析
    cmd_id = data[GWIN_REMOTE_PROT_INDEX_CMD];
    rand_id = data[GWIN_REMOTE_PROT_INDEX_RAND];
    // 数据解密
    if (!is_cleartext_prot)
    {
        gwin_security_decrypted_data_public_key(cmd_id, rand_id, &data[GWIN_REMOTE_PROT_ENCRYPTED_START], decrypted_data, GWIN_REMOTE_PROT_ENCRYPTED_LEN);
    }
    else
    {
        memcpy(decrypted_data, &data[GWIN_REMOTE_PROT_ENCRYPTED_START], GWIN_REMOTE_PROT_ENCRYPTED_LEN);
    }
    btn_id = decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_BTN)];

    // 遥控数据解密后发送到串口
    uint8_t data_remote_to_uart[31] = { 0x00 };
    memcpy(data_remote_to_uart, data, len < sizeof(data_remote_to_uart) ? len : sizeof(data_remote_to_uart));
    memcpy(&data_remote_to_uart[GWIN_REMOTE_PROT_ENCRYPTED_START], decrypted_data, GWIN_REMOTE_PROT_ENCRYPTED_LEN);
    gwin_protocol_data_recv(PROTOCOL_TASK_DATA_WAY_REMOTE, data_remote_to_uart, len);

    // 遥控配对预处理
    if (gwin_remote_pair(remote_pair_info, btn_id, &action))
    {
        if (action > 0)
        {
            goto GWIN_REMOTE_ACTION;
        }
        return;
    }

GWIN_REMOTE_ACTION:

    GWIN_DEBUG("%02x%02x%02x%02x : group_id = 0x%04x, cmd_id = 0x%02x, rand_id = 0x%02x, btn_id = 0x%02x",
                                remote_pair_info->remote_id[0], remote_pair_info->remote_id[1], remote_pair_info->remote_id[2], remote_pair_info->remote_id[3], remote_pair_info->group_id, cmd_id, rand_id, btn_id);

    if (action > 0)
    {
        *_action = action;
    }
}


/*-------------------------- END OF FILE ------------------------------------*/

